/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package msnserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ListModel;
import msncommonsc.ClienteRMI;
import msncommonsc.Contacto;
import msncommonsc.EnumEstado;
import msncommonsc.GuardarC;
import msncommonsc.MensajeDTO;
import msncommonsc.Persona;
import msncommonsc.ServidorRMI;

/**
 *
 * @author Martin
 */
public class Servidor extends UnicastRemoteObject implements ServidorRMI {

    private static Servidor instancia;
    private List< ClienteRMI> mapaClientes = new ArrayList<ClienteRMI>();
    private OListaServer oS ;

    public OListaServer getoS() {
        return oS;
    }

    public void setoS(OListaServer oS) {
        this.oS = oS;
    }

    private Servidor() throws RemoteException {
    }

    public static Servidor getInstancia() throws RemoteException, IOException {
        if (instancia == null) {
            instancia = new Servidor();
        }
        return instancia;

    }

    public List<ClienteRMI> getMapaClientes() {
        return mapaClientes;
    }

    public void setMapaClientes(List<ClienteRMI> mapaClientes) {
        this.mapaClientes = mapaClientes;
    }

    public void levantar() throws RemoteException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            Registry r = LocateRegistry.createRegistry(8080);
            r.rebind("SRMI", this);
            System.out.println("Servidor en linea");
            oS.notificarAccion("Servidor", "Servidor en linea");
            GuardarC.getInstance().guardarLog("Servidor", "Servidor en linea");
        } catch (RemoteException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public Persona cambiarDatosPersonales(String nombre, String contraseña, String nick) throws RemoteException {
        try {
            ControladoraPersona cp = ControladoraPersona.getInstance();
            Persona p = cp.cambiarDatos(nombre, contraseña, nick);
            if (!nick.equals("")) {
                cambiarNick(p);
            }
            oS.notificarAccion(nombre,"Cambio los datos personales");
            GuardarC.getInstance().guardarLog(nombre, "Cambio los datos personales");
            return p;
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public Persona conectar(String nombre, String contraseña, ClienteRMI cliente) throws RemoteException {
        Persona persona = new Persona();
        Contacto c = (Contacto) persona;
        c.setNombre("JPAXD");
        try {
            ControladoraPersona cp = ControladoraPersona.getInstance();
            Persona p = cp.obtenerPersona(nombre);
            if (!p.getNombre().equals("JPAXD") && p.getNombre().equals(nombre)) {
                if (p.getContraseña().equals(contraseña)) {
                    this.mapaClientes.add(cliente);
                    oS.notificarAccion(nombre,"Se a conectado");
                    GuardarC.getInstance().guardarLog(nombre, "Se a conectado");
                    return p;
                } else {
                    return persona;
                }
            } else {
                return persona;
            }
        } catch (Exception e) {
            throw new UnsupportedOperationException(e.toString());

        }
    }

    @Override
    public void cambiarNick(Persona persona) throws RemoteException {
        try {
            for (int i = 0; i < this.mapaClientes.size(); i++) {
                ClienteRMI c = (ClienteRMI) this.mapaClientes.get(i);
                Persona p = c.obtenerPersona();
                for (Contacto p2 : p.getMapaContactos()) {
                    if (p2.getNombre().equals(persona.getNombre())) {
                        c.notificarNick(persona.getNick(), persona.getNombre());
                    }
                }
            }
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public Persona agregarContacto(Persona persona, Contacto contacto) throws RemoteException {
        ControladoraPersona cp = ControladoraPersona.getInstance();
        Persona p = cp.agrgarContacto(persona, contacto);
        oS.notificarAccion(persona.getNombre(),"Agrego un contacto");
        try {
            GuardarC.getInstance().guardarLog(persona.getNombre(), "Agrego un contacto");
        } catch (IOException ex) {
            Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return p;

    }

    @Override
    public Boolean desconectar(String nombre) throws RemoteException {
        try {
            boolean res = false;
            cambiarEstado(nombre, EnumEstado.DESCONECTADO);
            for (int i = 0; i < this.mapaClientes.size(); i++) {
                ClienteRMI c = (ClienteRMI) this.mapaClientes.get(i);
                if (c.obtenerPersona().getNombre().equals(nombre)) {
                    this.mapaClientes.remove(c);
                    res = true;
                    oS.notificarAccion(nombre,"Se a desconectado");
                    GuardarC.getInstance().guardarLog(nombre, "Se a desconectado");
                }
            }
            return res;
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    @Override
    public Boolean crearCuenta(Persona persona) throws RemoteException {
        ControladoraPersona cp = ControladoraPersona.getInstance();
        Persona p = cp.obtenerPersona(persona.getNombre());
        try {
            if (!persona.equals(p)) {
                if (!p.getNombre().equals(persona.getNombre())) {
                    cp.persistirPersona(persona);
                    System.out.println("Cuenta nueva agregada");
                    oS.notificarAccion(persona.getNombre(),"Cuenta nueva agregada");
                    GuardarC.getInstance().guardarLog(persona.getNombre(), "Cuenta nueva agregada");
                    return true;
                } else {
                    System.out.println("Cuenta nueva no agregada");
                    return false;
                }
            } else {
                System.out.println("Cuenta nueva no agregada");
                return false;
            }
        } catch (Exception e) {
            throw new UnsupportedOperationException(e.toString());
        }


    }

    public void cambiarEstado(String nombre, EnumEstado estado) throws RemoteException {
        try {
            ControladoraPersona cp = ControladoraPersona.getInstance();
            cp.cambiarEstado(estado, nombre);
            for (int i = 0; i < this.mapaClientes.size(); i++) {
                ClienteRMI c = (ClienteRMI) this.mapaClientes.get(i);
                Persona p = c.obtenerPersona();
                for (Contacto p2 : p.getMapaContactos()) {
                    if (p2.getNombre().equals(nombre)) {
                        c.notificarEstado(nombre, estado);
                        oS.notificarAccion(nombre,"Cambio el estado a "+ estado.toString());
                        GuardarC.getInstance().guardarLog(nombre, "Cambio el estado a "+ estado.toString());
                    }
                }
            }
        } catch (Exception e) {
            throw new UnsupportedOperationException(e.toString());
        }
    }

    public Boolean enviarMensaje(MensajeDTO mensaje) throws RemoteException {
        try {
            Boolean aux = true;
            for (int i = 0; i < this.mapaClientes.size(); i++) {
                ClienteRMI c = (ClienteRMI) this.mapaClientes.get(i);
                Persona p = c.obtenerPersona();
                if (p.getNombre().equals(mensaje.getDestino())) {
                    if (p.getEstado().equals(EnumEstado.DESCONECTADO.toString())) {
                        aux = false;
                    }
                    c.recibirMensaje(mensaje);
                    oS.notificarAccion(mensaje.getOrigen(),"Envio un mensaje a "+mensaje.getDestino());
                    GuardarC.getInstance().guardarLog(mensaje.getOrigen(), "Envio un mensaje a "+mensaje.getDestino());
                }
            }
            return aux;
        } catch (Exception e) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    public void guardarCombersacion(String nombre, Boolean boo) throws RemoteException{
        try {
            ControladoraPersona.getInstance().guardarCombersacion(nombre, boo);
        } catch (Exception e) {
            throw new UnsupportedOperationException(e.toString());
        }

    }
}
